﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Crom.Controls.Docking;
using System.IO;
using System.Diagnostics;

namespace UI
{
    public partial class FrmSimulation : Form 
    {
        Dictionary<string, FrmSiteOutput> site_output = null;

        Dictionary<string, FrmMapOutput> Maps = new Dictionary<string, FrmMapOutput>();

        Dictionary<string, FrmSimulation> SubDirectoryMonitors = null;

        public event EventHandler SendMessage;

        string[] PathNames =null;
       
        public FrmSimulation(string text, string[] PathNames)
        {
            InitializeComponent();

            this.Text = PathNames[0];

            this.PathNames = PathNames;
          
          
            SubDirectoryMonitors = new Dictionary<string, FrmSimulation>();
            site_output = new Dictionary<string, FrmSiteOutput>();

           
             
            bgw_CreateSubFolders.RunWorkerAsync();
            
            bgw_ReadMaps.RunWorkerAsync();
           
            bgw_AddSiteOutputWindows.RunWorkerAsync();
            
        }
         
        
        string[] OutputFiles(string SearchPattern)
        {
           
            List<string> output_files = new List<string>();



            if (PathNames != null)
            {
                foreach (string path in PathNames)
                {
                    if (System.IO.Directory.Exists(path))
                    {
                        output_files.AddRange(new List<string>(System.IO.Directory.GetFiles(path)));
                    }
                    else if (System.IO.File.Exists(path))
                    {
                        output_files.Add(path);
                    }
                }
            }
            SearchPattern = SearchPattern.Replace("*","");

            return output_files.Where(o => o.ToLower().Contains(SearchPattern.ToLower())).ToArray();
        }



        string[] GetMapLabels( List<string> FileNames)
        {
            List<string> MapLabels = new List<string>();

            foreach (string File in FileNames)
            {
                string[] NewMapLabels = FrmSiteOutput.GetMapLabels(File);

                if (NewMapLabels != null)
                {
                    MapLabels.AddRange(NewMapLabels);
                }
            }
            return  new HashSet<string>(MapLabels).ToArray();
        }

        public static string GetWindowLabel(string FileName)
        {
            try
            {
                if (FileName.Contains("output") == false) return System.IO.Path.GetFileNameWithoutExtension(FileName);

                string[] terms = Path.GetFileNameWithoutExtension(FileName).Split('_');

                return terms[0];

               
            }
            catch (System.Exception e)
            {
                throw new Exception("Cannot determine Window Label "+ e.Message);
            }
        }
        

        private void MySendMessage(string msg)
        {
            if (this.SendMessage != null)
            {
                this.SendMessage((object)msg, new EventArgs());
            }
        }

       
        private void bgw_CreateSubFolders_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // If there is a single path name only
            
            if (PathNames == null || PathNames.Count() != 1) return;

             
                List<string> NewSubDirectories = null;

                
                if (System.IO.Directory.Exists(PathNames[0]))
                {
                    NewSubDirectories = new List<string>(System.IO.Directory.GetDirectories(PathNames[0]).Where(f => SubDirectoryMonitors.Keys.Contains(f) == false));
                }

                if (NewSubDirectories != null && NewSubDirectories.Count() > 0) MySendMessage("\t Adding Subdirectories");
                else return;
            

                foreach (string Folder in NewSubDirectories)
                {
                    MySendMessage("\t" + Folder);

                    FrmSimulation frm = new FrmSimulation(Folder, new string[] { PathNames[0] });

                    SubDirectoryMonitors.Add(Folder, frm);

                    Crom.Controls.Docking.DockableFormInfo form_info = this.dockContainer1.Add(frm, Crom.Controls.Docking.zAllowedDock.All, Guid.NewGuid());

                    this.dockContainer1.DockForm(form_info, DockStyle.Top, Crom.Controls.Docking.zDockMode.None);

                    this.dockContainer1.SetAutoHide(form_info, true);

                    frm.Show();
                    this.Refresh();
                }
             

        }

        private void bgw_ReadMaps_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                List<string> output_files = new List<string>(OutputFiles("*.img"));

                output_files.AddRange(new List<string>(OutputFiles("*.gis")));
                 

                if (output_files.Count() == 0) return;

                MySendMessage("Adding " + output_files.Count() + " maps");

                foreach (string FileName in output_files)
                {

                    MySendMessage("\t " + FileName);

                    string WindowLabel = GetWindowLabel(FileName);

                    if (Maps.ContainsKey(WindowLabel) == false)
                    { 
                        FrmMapOutput f = new FrmMapOutput(WindowLabel);
                        Maps.Add(WindowLabel, f);

                        f.SendMessage += this.SendMessage;

                        DockableFormInfo df = dockContainer1.Add(f, zAllowedDock.All, Guid.NewGuid());

                        this.dockContainer1.DockForm(df, DockStyle.Top, zDockMode.None);

                        //this.dockContainer1.SetAutoHide(df, true);
                    }

                    if (Maps.ContainsKey(WindowLabel))
                    {
                        Maps[WindowLabel].AddLayerData(FileName);
                    }

                }
                MySendMessage("Ready adding maps");


            }
            catch (System.Exception error)
            {
                MySendMessage(error.Message);
            }
        }

        /// ////////////////////////////////////////////////////////////////////////

        private void bgw_ReadCurves_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (string file in ouput_files)
            {
                MySendMessage("\t" + file);

                string[] MapLabels = FrmSiteOutput.GetMapLabels(file);

                if (MapLabels == null) continue;

                // Read the file if there is a suitable protocol for it
                FileContent f = new FileContent(file);

                if (f != null)
                {
                    int FirstDataColumn = 3;

                    double[] X = f.GetUnroundedYears<double>();

                    if (X == null)
                    {
                        X = f.GetColumn<double>("Time");
                        FirstDataColumn = 2;
                    }

                    for (int c = FirstDataColumn; c < f.Headers.Count(); c++)
                    {

                        double[] _Y = f.GetColumn<double>(f.Headers[c]);

                        

                        if (_Y != null)
                        {
                            foreach (string label in MapLabels)
                            {
                                site_output[label].AddCurve(X, _Y.ToArray(), file, f.Headers[c]);
                            }

                        }
                    }
                }
            }

        }
       
        /// ////////////////////////////////////////////////////////////////////////
        string[] MapLabels = null;
        List<string> ouput_files = new List<string>();
        private void bgw_AddSiteOutputWindows_DoWork(object sender, DoWorkEventArgs e)
        {
            
            MySendMessage("Reading dynamic output files");

            ouput_files = new List<string>(OutputFiles("*.csv"));
            ouput_files.AddRange(OutputFiles("*.txt").ToArray());
            
            if (ouput_files.Count() == 0)
            {
                MySendMessage("\t No Files");
                return;
            }
            

            MapLabels = GetMapLabels(ouput_files);


        }

        private void bgw_AddSiteOutputWindows_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (MapLabels == null || MapLabels.Count()==0) return;

            MySendMessage("\t Updating " + MapLabels.Count() + " curves.");

            foreach (string MapLabel in MapLabels)
            {
                if (site_output.ContainsKey(MapLabel) == false)
                {
                    FrmSiteOutput form = new FrmSiteOutput(MapLabel);//

                    site_output.Add(MapLabel, form);

                    dockContainer1.Add(form, zAllowedDock.All, Guid.NewGuid());

                }
            }
            bgw_ReadCurves.RunWorkerAsync();
        }

        private void bgw_AddSiteOutputWindows_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }
        

        
    }
}
